package work.thread_eg.concurrent.volatile_eg;

import java.util.concurrent.TimeUnit;

/**
 * 关于volatile关键字
 * 1) 线程可见性
 * 背景：JMM 每个线程都持有自己的工作内存 是对主内存的拷贝 对变量的更改是在线程的工作内存中进行更改 再写回主内存
 * 假如一个线程对一个变量更改了 立刻写回主内存 但是另外一个线程持有的还是旧值 什么时候再去主内存读取不可控制
 *
 * 原理：缓存一致性协议
 *
 * volatile线程可见性：简单来说 volatile变量更改之后  由于 MESI 缓存一致性协议 会导致其他线程工作内存中的值失效
 * 然后就只能再从主内存读取新的数据 底层是基于汇编的lock指令
 *
 * 在类中声明的变量是成员变量，也叫全局变量，放在堆中的（因为全局变量不会随着某个方法执行结束而销毁）
 **
 * 缓存行对齐： 缓存行对齐是为了提高效率
 * 缓存行大小是64个字节 相邻的数据放在同一个缓存行 会一起读取 CPU从主存读取数据到缓存是以缓存行为单位的
 * volatile数据一致性 在CPU级别是以缓存行为单位的
 *
 * volatile底层汇编lock指令会锁定共享变量所在的所有缓存行
 * volatile声明才使得所有与volatile字段相关的缓存行失效 缓存行失效之后就会再从主内存读取
 *
 * 2) 禁止指令重排 (参考 SingleTest04类)
 * 指令重排序（乱序执行): 彼此不影响的代码 CPU执行的时候会乱序 多线程的情况下会出现问题
 *
 * 原理：通过添加内存屏障
 * （CPU乱序本身是为了提高效率 不影响最后结果）
 *
 * 内存屏障：屏障两边的指令不能重排
 * 实现过程：
 * 1 java volatile关键字
 * 2 字节码文件加了标记 ACC_VOLATILE
 * 3 jvm的内存屏障
 *      屏障两边的指令不能重排
 * 4 hotspot实现 C++实现 汇编lock指令
 *
 */
public class VolatileTest {

    volatile boolean runnuing = true;
    void m() {
        System.out.println("m start");
        while(runnuing) {

        }
        System.out.println("m end");
    }

    public static void main(String[] args) {
        VolatileTest t = new VolatileTest();
        new Thread(t::m,"t1").start();
        try{
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.runnuing = false;
    }
}
